home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Resources / Developers / XAMPP 1.5.4 / Windows installer / xampp-win32-1.5.4-installer.exe / xampp / php / pear / PEAR / Config.php < prev    next >
Encoding:
PHP Script  |  2005-12-02  |  67.3 KB  |  2,055 lines

  1. <?php
  2. /**
  3.  * PEAR_Config, customized configuration handling for the PEAR Installer
  4.  *
  5.  * PHP versions 4 and 5
  6.  *
  7.  * LICENSE: This source file is subject to version 3.0 of the PHP license
  8.  * that is available through the world-wide-web at the following URI:
  9.  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  10.  * the PHP License and are unable to obtain it through the web, please
  11.  * send a note to license@php.net so we can mail you a copy immediately.
  12.  *
  13.  * @category   pear
  14.  * @package    PEAR
  15.  * @author     Stig Bakken <ssb@php.net>
  16.  * @author     Greg Beaver <cellog@php.net>
  17.  * @copyright  1997-2005 The PHP Group
  18.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  19.  * @version    CVS: $Id: Config.php,v 1.122 2005/11/03 04:52:26 cellog Exp $
  20.  * @link       http://pear.php.net/package/PEAR
  21.  * @since      File available since Release 0.1
  22.  */
  23.  
  24. /**
  25.  * Required for error handling
  26.  */
  27. require_once 'PEAR.php';
  28. require_once 'PEAR/Registry.php';
  29. require_once 'PEAR/Installer/Role.php';
  30. require_once 'System.php';
  31. require_once 'PEAR/Remote.php';
  32.  
  33. /**
  34.  * Last created PEAR_Config instance.
  35.  * @var object
  36.  */
  37. $GLOBALS['_PEAR_Config_instance'] = null;
  38. if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) {
  39.     $PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear';
  40. } else {
  41.     $PEAR_INSTALL_DIR = PEAR_INSTALL_DIR;
  42. }
  43.  
  44. // Below we define constants with default values for all configuration
  45. // parameters except username/password.  All of them can have their
  46. // defaults set through environment variables.  The reason we use the
  47. // PHP_ prefix is for some security, PHP protects environment
  48. // variables starting with PHP_*.
  49.  
  50. // default channel and preferred mirror is based on whether we are invoked through
  51. // the "pear" or the "pecl" command
  52.  
  53. if (!defined('PEAR_RUNTYPE') || PEAR_RUNTYPE == 'pear') {
  54.     define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pear.php.net');
  55. } else {
  56.     define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pecl.php.net');
  57. }
  58.  
  59. if (getenv('PHP_PEAR_SYSCONF_DIR')) {
  60.     define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR'));
  61. } elseif (getenv('SystemRoot')) {
  62.     define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot'));
  63. } else {
  64.     define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR);
  65. }
  66.  
  67. // Default for master_server
  68. if (getenv('PHP_PEAR_MASTER_SERVER')) {
  69.     define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER'));
  70. } else {
  71.     define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net');
  72. }
  73.  
  74. // Default for http_proxy
  75. if (getenv('PHP_PEAR_HTTP_PROXY')) {
  76.     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY'));
  77. } elseif (getenv('http_proxy')) {
  78.     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy'));
  79. } else {
  80.     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', '');
  81. }
  82.  
  83. // Default for php_dir
  84. if (getenv('PHP_PEAR_INSTALL_DIR')) {
  85.     define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR'));
  86. } else {
  87.     if (@is_dir($PEAR_INSTALL_DIR)) {
  88.         define('PEAR_CONFIG_DEFAULT_PHP_DIR',
  89.                $PEAR_INSTALL_DIR);
  90.     } else {
  91.         define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);
  92.     }
  93. }
  94.  
  95. // Default for ext_dir
  96. if (getenv('PHP_PEAR_EXTENSION_DIR')) {
  97.     define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR'));
  98. } else {
  99.     if (ini_get('extension_dir')) {
  100.         define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir'));
  101.     } elseif (defined('PEAR_EXTENSION_DIR') && @is_dir(PEAR_EXTENSION_DIR)) {
  102.         define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR);
  103.     } elseif (defined('PHP_EXTENSION_DIR')) {
  104.         define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR);
  105.     } else {
  106.         define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.');
  107.     }
  108. }
  109.  
  110. // Default for doc_dir
  111. if (getenv('PHP_PEAR_DOC_DIR')) {
  112.     define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR'));
  113. } else {
  114.     define('PEAR_CONFIG_DEFAULT_DOC_DIR',
  115.            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs');
  116. }
  117.  
  118. // Default for bin_dir
  119. if (getenv('PHP_PEAR_BIN_DIR')) {
  120.     define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR'));
  121. } else {
  122.     define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR);
  123. }
  124.  
  125. // Default for data_dir
  126. if (getenv('PHP_PEAR_DATA_DIR')) {
  127.     define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR'));
  128. } else {
  129.     define('PEAR_CONFIG_DEFAULT_DATA_DIR',
  130.            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data');
  131. }
  132.  
  133. // Default for test_dir
  134. if (getenv('PHP_PEAR_TEST_DIR')) {
  135.     define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR'));
  136. } else {
  137.     define('PEAR_CONFIG_DEFAULT_TEST_DIR',
  138.            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests');
  139. }
  140.  
  141. // Default for cache_dir
  142. if (getenv('PHP_PEAR_CACHE_DIR')) {
  143.     define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR'));
  144. } else {
  145.     define('PEAR_CONFIG_DEFAULT_CACHE_DIR',
  146.            System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
  147.            DIRECTORY_SEPARATOR . 'cache');
  148. }
  149.  
  150. // Default for php_bin
  151. if (getenv('PHP_PEAR_PHP_BIN')) {
  152.     define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN'));
  153. } else {
  154.     define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR.
  155.            DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : ''));
  156. }
  157.  
  158. // Default for verbose
  159. if (getenv('PHP_PEAR_VERBOSE')) {
  160.     define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE'));
  161. } else {
  162.     define('PEAR_CONFIG_DEFAULT_VERBOSE', 1);
  163. }
  164.  
  165. // Default for preferred_state
  166. if (getenv('PHP_PEAR_PREFERRED_STATE')) {
  167.     define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE'));
  168. } else {
  169.     define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable');
  170. }
  171.  
  172. // Default for umask
  173. if (getenv('PHP_PEAR_UMASK')) {
  174.     define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK'));
  175. } else {
  176.     define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask()));
  177. }
  178.  
  179. // Default for cache_ttl
  180. if (getenv('PHP_PEAR_CACHE_TTL')) {
  181.     define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL'));
  182. } else {
  183.     define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600);
  184. }
  185.  
  186. // Default for sig_type
  187. if (getenv('PHP_PEAR_SIG_TYPE')) {
  188.     define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE'));
  189. } else {
  190.     define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg');
  191. }
  192.  
  193. // Default for sig_bin
  194. if (getenv('PHP_PEAR_SIG_BIN')) {
  195.     define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN'));
  196. } else {
  197.     define('PEAR_CONFIG_DEFAULT_SIG_BIN',
  198.            System::which(
  199.                'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg'));
  200. }
  201.  
  202. // Default for sig_keydir
  203. if (getenv('PHP_PEAR_SIG_KEYDIR')) {
  204.     define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR'));
  205. } else {
  206.     define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR',
  207.            PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys');
  208. }
  209.  
  210. /**
  211.  * This is a class for storing configuration data, keeping track of
  212.  * which are system-defined, user-defined or defaulted.
  213.  * @category   pear
  214.  * @package    PEAR
  215.  * @author     Stig Bakken <ssb@php.net>
  216.  * @author     Greg Beaver <cellog@php.net>
  217.  * @copyright  1997-2005 The PHP Group
  218.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  219.  * @version    Release: 1.4.5
  220.  * @link       http://pear.php.net/package/PEAR
  221.  * @since      Class available since Release 0.1
  222.  */
  223. class PEAR_Config extends PEAR
  224. {
  225.     // {{{ properties
  226.  
  227.     /**
  228.      * Array of config files used.
  229.      *
  230.      * @var array layer => config file
  231.      */
  232.     var $files = array(
  233.         'system' => '',
  234.         'user' => '',
  235.         );
  236.  
  237.     var $layers = array();
  238.     
  239.     /**
  240.      * Configuration data, two-dimensional array where the first
  241.      * dimension is the config layer ('user', 'system' and 'default'),
  242.      * and the second dimension is keyname => value.
  243.      *
  244.      * The order in the first dimension is important!  Earlier
  245.      * layers will shadow later ones when a config value is
  246.      * requested (if a 'user' value exists, it will be returned first,
  247.      * then 'system' and finally 'default').
  248.      *
  249.      * @var array layer => array(keyname => value, ...)
  250.      */
  251.     var $configuration = array(
  252.         'user' => array(),
  253.         'system' => array(),
  254.         'default' => array(),
  255.         );
  256.     
  257.     /**
  258.      * Configuration values that can be set for a channel
  259.      *
  260.      * All other configuration values can only have a global value
  261.      * @var array
  262.      * @access private
  263.      */
  264.     var $_channelConfigInfo = array(
  265.         'php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir',
  266.         'test_dir', 'php_bin', 'username', 'password', 'verbose',
  267.         'preferred_state', 'umask', 'preferred_mirror',
  268.         );
  269.  
  270.     /**
  271.      * Channels that can be accessed
  272.      * @see setChannels()
  273.      * @var array
  274.      * @access private
  275.      */
  276.     var $_channels = array('pear.php.net', 'pecl.php.net', '__uri');
  277.  
  278.     /**
  279.      * This variable is used to control the directory values returned
  280.      * @see setInstallRoot();
  281.      * @var string|false
  282.      * @access private
  283.      */
  284.     var $_installRoot = false;
  285.  
  286.     /**
  287.      * If requested, this will always refer to the registry
  288.      * contained in php_dir
  289.      * @var PEAR_Registry
  290.      */
  291.     var $_registry = array();
  292.  
  293.     /**
  294.      * @var array
  295.      * @access private
  296.      */
  297.     var $_regInitialized = array();
  298.  
  299.     /**
  300.      * @var bool
  301.      * @access private
  302.      */
  303.     var $_noRegistry = false;
  304.  
  305.     /**
  306.      * amount of errors found while parsing config
  307.      * @var integer
  308.      * @access private
  309.      */
  310.     var $_errorsFound = 0;
  311.     var $_lastError = null;
  312.  
  313.     /**
  314.      * Information about the configuration data.  Stores the type,
  315.      * default value and a documentation string for each configuration
  316.      * value.
  317.      *
  318.      * @var array layer => array(infotype => value, ...)
  319.      */
  320.     var $configuration_info = array(
  321.         // Channels/Internet Access
  322.         'default_channel' => array(
  323.             'type' => 'string',
  324.             'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
  325.             'doc' => 'the default channel to use for all non explicit commands',
  326.             'prompt' => 'Default Channel',
  327.             'group' => 'Internet Access',
  328.             ),
  329.         'preferred_mirror' => array(
  330.             'type' => 'string',
  331.             'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
  332.             'doc' => 'the default server or mirror to use for channel actions',
  333.             'prompt' => 'Default Channel Mirror',
  334.             'group' => 'Internet Access',
  335.             ),
  336.         'remote_config' => array(
  337.             'type' => 'password',
  338.             'default' => '',
  339.             'doc' => 'ftp url of remote configuration file to use for synchronized install',
  340.             'prompt' => 'Remote Configuration File',
  341.             'group' => 'Internet Access',
  342.             ),
  343.         'auto_discover' => array(
  344.             'type' => 'integer',
  345.             'default' => 0,
  346.             'doc' => 'whether to automatically discover new channels',
  347.             'prompt' => 'Auto-discover new Channels',
  348.             'group' => 'Internet Access',
  349.             ),
  350.         // Internet Access
  351.         'master_server' => array(
  352.             'type' => 'string',
  353.             'default' => 'pear.php.net',
  354.             'doc' => 'name of the main PEAR server [NOT USED IN THIS VERSION]',
  355.             'prompt' => 'PEAR server [DEPRECATED]',
  356.             'group' => 'Internet Access',
  357.             ),
  358.         'http_proxy' => array(
  359.             'type' => 'string',
  360.             'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY,
  361.             'doc' => 'HTTP proxy (host:port) to use when downloading packages',
  362.             'prompt' => 'HTTP Proxy Server Address',
  363.             'group' => 'Internet Access',
  364.             ),
  365.         // File Locations
  366.         'php_dir' => array(
  367.             'type' => 'directory',
  368.             'default' => PEAR_CONFIG_DEFAULT_PHP_DIR,
  369.             'doc' => 'directory where .php files are installed',
  370.             'prompt' => 'PEAR directory',
  371.             'group' => 'File Locations',
  372.             ),
  373.         'ext_dir' => array(
  374.             'type' => 'directory',
  375.             'default' => PEAR_CONFIG_DEFAULT_EXT_DIR,
  376.             'doc' => 'directory where loadable extensions are installed',
  377.             'prompt' => 'PHP extension directory',
  378.             'group' => 'File Locations',
  379.             ),
  380.         'doc_dir' => array(
  381.             'type' => 'directory',
  382.             'default' => PEAR_CONFIG_DEFAULT_DOC_DIR,
  383.             'doc' => 'directory where documentation is installed',
  384.             'prompt' => 'PEAR documentation directory',
  385.             'group' => 'File Locations',
  386.             ),
  387.         'bin_dir' => array(
  388.             'type' => 'directory',
  389.             'default' => PEAR_CONFIG_DEFAULT_BIN_DIR,
  390.             'doc' => 'directory where executables are installed',
  391.             'prompt' => 'PEAR executables directory',
  392.             'group' => 'File Locations',
  393.             ),
  394.         'data_dir' => array(
  395.             'type' => 'directory',
  396.             'default' => PEAR_CONFIG_DEFAULT_DATA_DIR,
  397.             'doc' => 'directory where data files are installed',
  398.             'prompt' => 'PEAR data directory',
  399.             'group' => 'File Locations (Advanced)',
  400.             ),
  401.         'test_dir' => array(
  402.             'type' => 'directory',
  403.             'default' => PEAR_CONFIG_DEFAULT_TEST_DIR,
  404.             'doc' => 'directory where regression tests are installed',
  405.             'prompt' => 'PEAR test directory',
  406.             'group' => 'File Locations (Advanced)',
  407.             ),
  408.         'cache_dir' => array(
  409.             'type' => 'directory',
  410.             'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR,
  411.             'doc' => 'directory which is used for XMLRPC cache',
  412.             'prompt' => 'PEAR Installer cache directory',
  413.             'group' => 'File Locations (Advanced)',
  414.             ),
  415.         'php_bin' => array(
  416.             'type' => 'file',
  417.             'default' => PEAR_CONFIG_DEFAULT_PHP_BIN,
  418.             'doc' => 'PHP CLI/CGI binary for executing scripts',
  419.             'prompt' => 'PHP CLI/CGI binary',
  420.             'group' => 'File Locations (Advanced)',
  421.             ),
  422.         // Maintainers
  423.         'username' => array(
  424.             'type' => 'string',
  425.             'default' => '',
  426.             'doc' => '(maintainers) your PEAR account name',
  427.             'prompt' => 'PEAR username (for maintainers)',
  428.             'group' => 'Maintainers',
  429.             ),
  430.         'password' => array(
  431.             'type' => 'password',
  432.             'default' => '',
  433.             'doc' => '(maintainers) your PEAR account password',
  434.             'prompt' => 'PEAR password (for maintainers)',
  435.             'group' => 'Maintainers',
  436.             ),
  437.         // Advanced
  438.         'verbose' => array(
  439.             'type' => 'integer',
  440.             'default' => PEAR_CONFIG_DEFAULT_VERBOSE,
  441.             'doc' => 'verbosity level
  442. 0: really quiet
  443. 1: somewhat quiet
  444. 2: verbose
  445. 3: debug',
  446.             'prompt' => 'Debug Log Level',
  447.             'group' => 'Advanced',
  448.             ),
  449.         'preferred_state' => array(
  450.             'type' => 'set',
  451.             'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE,
  452.             'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified',
  453.             'valid_set' => array(
  454.                 'stable', 'beta', 'alpha', 'devel', 'snapshot'),
  455.             'prompt' => 'Preferred Package State',
  456.             'group' => 'Advanced',
  457.             ),
  458.         'umask' => array(
  459.             'type' => 'mask',
  460.             'default' => PEAR_CONFIG_DEFAULT_UMASK,
  461.             'doc' => 'umask used when creating files (Unix-like systems only)',
  462.             'prompt' => 'Unix file mask',
  463.             'group' => 'Advanced',
  464.             ),
  465.         'cache_ttl' => array(
  466.             'type' => 'integer',
  467.             'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL,
  468.             'doc' => 'amount of secs where the local cache is used and not updated',
  469.             'prompt' => 'Cache TimeToLive',
  470.             'group' => 'Advanced',
  471.             ),
  472.         'sig_type' => array(
  473.             'type' => 'set',
  474.             'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE,
  475.             'doc' => 'which package signature mechanism to use',
  476.             'valid_set' => array('gpg'),
  477.             'prompt' => 'Package Signature Type',
  478.             'group' => 'Maintainers',
  479.             ),
  480.         'sig_bin' => array(
  481.             'type' => 'string',
  482.             'default' => PEAR_CONFIG_DEFAULT_SIG_BIN,
  483.             'doc' => 'which package signature mechanism to use',
  484.             'prompt' => 'Signature Handling Program',
  485.             'group' => 'Maintainers',
  486.             ),
  487.         'sig_keyid' => array(
  488.             'type' => 'string',
  489.             'default' => '',
  490.             'doc' => 'which key to use for signing with',
  491.             'prompt' => 'Signature Key Id',
  492.             'group' => 'Maintainers',
  493.             ),
  494.         'sig_keydir' => array(
  495.             'type' => 'directory',
  496.             'default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR,
  497.             'doc' => 'directory where signature keys are located',
  498.             'prompt' => 'Signature Key Directory',
  499.             'group' => 'Maintainers',
  500.             ),
  501.         // __channels is reserved - used for channel-specific configuration
  502.         );
  503.  
  504.     // }}}
  505.  
  506.     // {{{ PEAR_Config([file], [defaults_file])
  507.  
  508.     /**
  509.      * Constructor.
  510.      *
  511.      * @param string file to read user-defined options from
  512.      * @param string file to read system-wide defaults from
  513.      * @param bool   determines whether a registry object "follows"
  514.      *               the value of php_dir (is automatically created
  515.      *               and moved when php_dir is changed)
  516.      * @param bool   if true, fails if configuration files cannot be loaded
  517.      *
  518.      * @access public
  519.      *
  520.      * @see PEAR_Config::singleton
  521.      */
  522.     function PEAR_Config($user_file = '', $system_file = '', $ftp_file = false,
  523.                          $strict = true)
  524.     {
  525.         $this->PEAR();
  526.         PEAR_Installer_Role::initializeConfig($this);
  527.         $sl = DIRECTORY_SEPARATOR;
  528.         if (empty($user_file)) {
  529.             if (OS_WINDOWS) {
  530.                 $user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini';
  531.             } else {
  532.                 $user_file = getenv('HOME') . $sl . '.pearrc';
  533.             }
  534.         }
  535.         if (empty($system_file)) {
  536.             if (OS_WINDOWS) {
  537.                 $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini';
  538.             } else {
  539.                 $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf';
  540.             }
  541.         }
  542.  
  543.         $this->layers = array_keys($this->configuration);
  544.         $this->files['user'] = $user_file;
  545.         $this->files['system'] = $system_file;
  546.         if ($user_file && @file_exists($user_file)) {
  547.             $this->pushErrorHandling(PEAR_ERROR_RETURN);
  548.             $this->readConfigFile($user_file, 'user', $strict);
  549.             $this->popErrorHandling();
  550.             if ($this->_errorsFound > 0) {
  551.                 return;
  552.             }
  553.         }
  554.  
  555.         if ($system_file && @file_exists($system_file)) {
  556.             $this->mergeConfigFile($system_file, false, 'system', $strict);
  557.             if ($this->_errorsFound > 0) {
  558.                 return;
  559.             }
  560.  
  561.         }
  562.  
  563.         if (!$ftp_file) {
  564.             $ftp_file = $this->get('remote_config');
  565.         }
  566.  
  567.         if ($ftp_file && defined('PEAR_REMOTEINSTALL_OK')) {
  568.             $this->readFTPConfigFile($ftp_file);
  569.         }
  570.  
  571.         foreach ($this->configuration_info as $key => $info) {
  572.             $this->configuration['default'][$key] = $info['default'];
  573.         }
  574.  
  575.         $this->_registry['default'] = &new PEAR_Registry($this->configuration['default']['php_dir']);
  576.         $this->_registry['default']->setConfig($this);
  577.         $this->_regInitialized['default'] = false;
  578.         //$GLOBALS['_PEAR_Config_instance'] = &$this;
  579.     }
  580.  
  581.     // }}}
  582.     // {{{ singleton([file], [defaults_file])
  583.  
  584.     /**
  585.      * Static singleton method.  If you want to keep only one instance
  586.      * of this class in use, this method will give you a reference to
  587.      * the last created PEAR_Config object if one exists, or create a
  588.      * new object.
  589.      *
  590.      * @param string (optional) file to read user-defined options from
  591.      * @param string (optional) file to read system-wide defaults from
  592.      *
  593.      * @return object an existing or new PEAR_Config instance
  594.      *
  595.      * @access public
  596.      *
  597.      * @see PEAR_Config::PEAR_Config
  598.      */
  599.     function &singleton($user_file = '', $system_file = '', $strict = true)
  600.     {
  601.         if (is_object($GLOBALS['_PEAR_Config_instance'])) {
  602.             return $GLOBALS['_PEAR_Config_instance'];
  603.         }
  604.  
  605.         $t_conf = &new PEAR_Config($user_file, $system_file, false, $strict);
  606.         if ($t_conf->_errorsFound > 0) {
  607.              return $t_conf->lastError;
  608.         }
  609.  
  610.         $GLOBALS['_PEAR_Config_instance'] = &$t_conf;
  611.         return $GLOBALS['_PEAR_Config_instance'];
  612.     }
  613.  
  614.     // }}}
  615.     // {{{ validConfiguration()
  616.  
  617.     /**
  618.      * Determine whether any configuration files have been detected, and whether a
  619.      * registry object can be retrieved from this configuration.
  620.      * @return bool
  621.      * @since PEAR 1.4.0a1
  622.      */
  623.     function validConfiguration()
  624.     {
  625.         if ($this->isDefinedLayer('user') || $this->isDefinedLayer('system')) {
  626.             return true;
  627.         }
  628.         return false;
  629.     }
  630.  
  631.     // }}}
  632.     // {{{ readConfigFile([file], [layer])
  633.  
  634.     /**
  635.      * Reads configuration data from a file.  All existing values in
  636.      * the config layer are discarded and replaced with data from the
  637.      * file.
  638.      * @param string file to read from, if NULL or not specified, the
  639.      *               last-used file for the same layer (second param) is used
  640.      * @param string config layer to insert data into ('user' or 'system')
  641.      * @return bool TRUE on success or a PEAR error on failure
  642.      */
  643.     function readConfigFile($file = null, $layer = 'user', $strict = true)
  644.     {
  645.         if (empty($this->files[$layer])) {
  646.             return $this->raiseError("unknown config layer `$layer'");
  647.         }
  648.  
  649.         if ($file === null) {
  650.             $file = $this->files[$layer];
  651.         }
  652.  
  653.         $data = $this->_readConfigDataFrom($file);
  654.  
  655.         if (PEAR::isError($data)) {
  656.             if ($strict) {
  657.                 $this->_errorsFound++;
  658.                 $this->lastError = $data;
  659.  
  660.                 return $data;
  661.             } else {
  662.                 return true;
  663.             }
  664.         } else {
  665.             $this->files[$layer] = $file;
  666.         }
  667.  
  668.         $this->_decodeInput($data);
  669.         $this->configuration[$layer] = $data;
  670.         $this->_setupChannels();
  671.         if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
  672.             $this->_registry[$layer] = &new PEAR_Registry($phpdir);
  673.             $this->_registry[$layer]->setConfig($this);
  674.             $this->_regInitialized[$layer] = false;
  675.         } else {
  676.             unset($this->_registry[$layer]);
  677.         }
  678.         return true;
  679.     }
  680.  
  681.     // }}}
  682.  
  683.     /**
  684.      * @param string url to the remote config file, like ftp://www.example.com/pear/config.ini
  685.      * @return true|PEAR_Error
  686.      */
  687.     function readFTPConfigFile($path)
  688.     {
  689.         do { // poor man's try
  690.             if (!class_exists('Net_FTP')) {
  691.                 if (!class_exists('PEAR_Common')) {
  692.                     require_once 'PEAR/Common.php';
  693.                 }
  694.                 if (PEAR_Common::isIncludeable('Net/FTP.php')) {
  695.                     include_once 'Net/FTP.php';
  696.                 }
  697.             }
  698.             if (class_exists('Net_FTP') &&
  699.                   (class_exists('PEAR_FTP') || PEAR_Common::isIncludeable('PEAR/FTP.php'))) {
  700.                 require_once 'PEAR/FTP.php';
  701.                 $this->_ftp = &new PEAR_FTP;
  702.                 $this->_ftp->pushErrorHandling(PEAR_ERROR_RETURN);
  703.                 $e = $this->_ftp->init($path);
  704.                 if (PEAR::isError($e)) {
  705.                     $this->_ftp->popErrorHandling();
  706.                     return $e;
  707.                 }
  708.                 $tmp = System::mktemp('-d');
  709.                 PEAR_Common::addTempFile($tmp);
  710.                 $e = $this->_ftp->get(basename($path), $tmp . DIRECTORY_SEPARATOR .
  711.                     'pear.ini', false, FTP_BINARY);
  712.                 if (PEAR::isError($e)) {
  713.                     $this->_ftp->popErrorHandling();
  714.                     return $e;
  715.                 }
  716.                 PEAR_Common::addTempFile($tmp . DIRECTORY_SEPARATOR . 'pear.ini');
  717.                 $this->_ftp->disconnect();
  718.                 $this->_ftp->popErrorHandling();
  719.                 $this->files['ftp'] = $tmp . DIRECTORY_SEPARATOR . 'pear.ini';
  720.                 $e = $this->readConfigFile(null, 'ftp');
  721.                 if (PEAR::isError($e)) {
  722.                     return $e;
  723.                 }
  724.                 $fail = array();
  725.                 foreach ($this->configuration_info as $key => $val) {
  726.                     if (in_array($this->getGroup($key),
  727.                           array('File Locations', 'File Locations (Advanced)')) &&
  728.                           $this->getType($key) == 'directory') {
  729.                         // any directory configs must be set for this to work
  730.                         if (!isset($this->configuration['ftp'][$key])) {
  731.                             $fail[] = $key;
  732.                         }
  733.                     }
  734.                 }
  735.                 if (count($fail)) {
  736.                     $fail = '"' . implode('", "', $fail) . '"';
  737.                     unset($this->files['ftp']);
  738.                     unset($this->configuration['ftp']);
  739.                     return PEAR::raiseError('ERROR: Ftp configuration file must set all ' .
  740.                         'directory configuration variables.  These variables were not set: ' .
  741.                         $fail);
  742.                 } else {
  743.                     return true;
  744.                 }
  745.             } else {
  746.                 return PEAR::raiseError('Net_FTP must be installed to use remote config');
  747.             }
  748.         } while (false); // poor man's catch
  749.         unset($this->files['ftp']);
  750.         return PEAR::raiseError('no remote host specified');
  751.     }
  752.  
  753.     // {{{ _setupChannels()
  754.     
  755.     /**
  756.      * Reads the existing configurations and creates the _channels array from it
  757.      */
  758.     function _setupChannels()
  759.     {
  760.         $set = array_flip(array_values($this->_channels));
  761.         foreach ($this->configuration as $layer => $data) {
  762.             $i = 1000;
  763.             if (isset($data['__channels'])) {
  764.                 foreach ($data['__channels'] as $channel => $info) {
  765.                     $set[$channel] = $i++;
  766.                 }
  767.             }
  768.         }
  769.         $this->_channels = array_values(array_flip($set));
  770.         $this->setChannels($this->_channels);
  771.     }
  772.  
  773.     // }}}
  774.     // {{{ deleteChannel(channel)
  775.  
  776.     function deleteChannel($channel)
  777.     {
  778.         foreach ($this->configuration as $layer => $data) {
  779.             if (isset($data['__channels'])) {
  780.                 if (isset($data['__channels'][strtolower($channel)])) {
  781.                     unset($this->configuration[$layer]['__channels'][strtolower($channel)]);
  782.                 }
  783.             }
  784.         }
  785.         $this->_channels = array_flip($this->_channels);
  786.         unset($this->_channels[strtolower($channel)]);
  787.         $this->_channels = array_flip($this->_channels);
  788.     }
  789.  
  790.     // }}}
  791.     // {{{ mergeConfigFile(file, [override], [layer])
  792.  
  793.     /**
  794.      * Merges data into a config layer from a file.  Does the same
  795.      * thing as readConfigFile, except it does not replace all
  796.      * existing values in the config layer.
  797.      * @param string file to read from
  798.      * @param bool whether to overwrite existing data (default TRUE)
  799.      * @param string config layer to insert data into ('user' or 'system')
  800.      * @param string if true, errors are returned if file opening fails
  801.      * @return bool TRUE on success or a PEAR error on failure
  802.      */
  803.     function mergeConfigFile($file, $override = true, $layer = 'user', $strict = true)
  804.     {
  805.         if (empty($this->files[$layer])) {
  806.             return $this->raiseError("unknown config layer `$layer'");
  807.         }
  808.         if ($file === null) {
  809.             $file = $this->files[$layer];
  810.         }
  811.         $data = $this->_readConfigDataFrom($file);
  812.         if (PEAR::isError($data)) {
  813.             if ($strict) {
  814.                 $this->_errorsFound++;
  815.                 $this->lastError = $data;
  816.  
  817.                 return $data;
  818.             } else {
  819.                 return true;
  820.             }
  821.         }
  822.         $this->_decodeInput($data);
  823.         if ($override) {
  824.             $this->configuration[$layer] =
  825.                 PEAR_Config::arrayMergeRecursive($this->configuration[$layer], $data);
  826.         } else {
  827.             $this->configuration[$layer] =
  828.                 PEAR_Config::arrayMergeRecursive($data, $this->configuration[$layer]);
  829.         }
  830.         $this->_setupChannels();
  831.         if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
  832.             $this->_registry[$layer] = &new PEAR_Registry($phpdir);
  833.             $this->_registry[$layer]->setConfig($this);
  834.             $this->_regInitialized[$layer] = false;
  835.         } else {
  836.             unset($this->_registry[$layer]);
  837.         }
  838.         return true;
  839.     }
  840.  
  841.     // }}}
  842.     // {{{ arrayMergeRecursive($arr2, $arr1)
  843.     /**
  844.      * @param array
  845.      * @param array
  846.      * @return array
  847.      * @static
  848.      */
  849.     function arrayMergeRecursive($arr2, $arr1)
  850.     {
  851.         $ret = array();
  852.         foreach ($arr2 as $key => $data) {
  853.             if (!isset($arr1[$key])) {
  854.                 $ret[$key] = $data;
  855.                 unset($arr1[$key]);
  856.                 continue;
  857.             }
  858.             if (is_array($data)) {
  859.                 if (!is_array($arr1[$key])) {
  860.                     $ret[$key] = $arr1[$key];
  861.                     unset($arr1[$key]);
  862.                     continue;
  863.                 }
  864.                 $ret[$key] = PEAR_Config::arrayMergeRecursive($arr1[$key], $arr2[$key]);
  865.                 unset($arr1[$key]);
  866.             }
  867.         }
  868.         return array_merge($ret, $arr1);
  869.     }
  870.  
  871.     // }}}
  872.     // {{{ writeConfigFile([file], [layer])
  873.  
  874.     /**
  875.      * Writes data into a config layer from a file.
  876.      *
  877.      * @param string|null file to read from, or null for default
  878.      * @param string config layer to insert data into ('user' or
  879.      *               'system')
  880.      * @param string|null data to write to config file or null for internal data [DEPRECATED]
  881.      * @return bool TRUE on success or a PEAR error on failure
  882.      */
  883.     function writeConfigFile($file = null, $layer = 'user', $data = null)
  884.     {
  885.         $this->_lazyChannelSetup($layer);
  886.         if ($layer == 'both' || $layer == 'all') {
  887.             foreach ($this->files as $type => $file) {
  888.                 $err = $this->writeConfigFile($file, $type, $data);
  889.                 if (PEAR::isError($err)) {
  890.                     return $err;
  891.                 }
  892.             }
  893.             return true;
  894.         }
  895.         if (empty($this->files[$layer])) {
  896.             return $this->raiseError("unknown config file type `$layer'");
  897.         }
  898.         if ($file === null) {
  899.             $file = $this->files[$layer];
  900.         }
  901.         $data = ($data === null) ? $this->configuration[$layer] : $data;
  902.         $this->_encodeOutput($data);
  903.         $opt = array('-p', dirname($file));
  904.         if (!@System::mkDir($opt)) {
  905.             return $this->raiseError("could not create directory: " . dirname($file));
  906.         }
  907.         if (@is_file($file) && !@is_writeable($file)) {
  908.             return $this->raiseError("no write access to $file!");
  909.         }
  910.         $fp = @fopen($file, "w");
  911.         if (!$fp) {
  912.             return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed");
  913.         }
  914.         $contents = "#PEAR_Config 0.9\n" . serialize($data);
  915.         if (!@fwrite($fp, $contents)) {
  916.             return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed");
  917.         }
  918.         return true;
  919.     }
  920.  
  921.     // }}}
  922.     // {{{ _readConfigDataFrom(file)
  923.  
  924.     /**
  925.      * Reads configuration data from a file and returns the parsed data
  926.      * in an array.
  927.      *
  928.      * @param string file to read from
  929.      *
  930.      * @return array configuration data or a PEAR error on failure
  931.      *
  932.      * @access private
  933.      */
  934.     function _readConfigDataFrom($file)
  935.     {
  936.         $fp = @fopen($file, "r");
  937.         if (!$fp) {
  938.             return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed");
  939.         }
  940.         $size = filesize($file);
  941.         $rt = get_magic_quotes_runtime();
  942.         set_magic_quotes_runtime(0);
  943.         if (function_exists('file_get_contents')) {
  944.             fclose($fp);
  945.             $contents = file_get_contents($file);
  946.         } else {
  947.             $contents = @fread($fp, $size);
  948.             fclose($fp);
  949.         }
  950.         if (empty($contents)) {
  951.             return $this->raiseError('Configuration file "' . $file . '" is empty');
  952.         }
  953.         
  954.         set_magic_quotes_runtime($rt);
  955.  
  956.         $version = false;
  957.         if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) {
  958.             $version = $matches[1];
  959.             $contents = substr($contents, strlen($matches[0]));
  960.         } else {
  961.             // Museum config file
  962.             if (substr($contents,0,2) == 'a:') {
  963.                 $version = '0.1';
  964.             }
  965.         }
  966.         if ($version && version_compare("$version", '1', '<')) {
  967.  
  968.             // no '@', it is possible that unserialize
  969.             // raises a notice but it seems to block IO to
  970.             // STDOUT if a '@' is used and a notice is raise
  971.             $data = unserialize($contents);
  972.  
  973.             if (!is_array($data) && !$data) {
  974.                 if ($contents == serialize(false)) {
  975.                     $data = array();
  976.                 } else {
  977.                     $err = $this->raiseError("PEAR_Config: bad data in $file");
  978.                     return $err;
  979.                 }
  980.             }
  981.             if (!is_array($data)) {
  982.                 if (strlen(trim($contents)) > 0) {
  983.                     $error = "PEAR_Config: bad data in $file";
  984.                     $err = $this->raiseError($error);
  985.                     return $err;
  986.                 } else {
  987.                     $data = array();
  988.                 }
  989.             }
  990.         // add parsing of newer formats here...
  991.         } else {
  992.             $err = $this->raiseError("$file: unknown version `$version'");
  993.             return $err; 
  994.         }
  995.         return $data;
  996.     }
  997.  
  998.     // }}}
  999.     // {{{ getConfFile(layer)
  1000.     /**
  1001.     * Gets the file used for storing the config for a layer
  1002.     *
  1003.     * @param string $layer 'user' or 'system'
  1004.     */
  1005.  
  1006.     function getConfFile($layer)
  1007.     {
  1008.         return $this->files[$layer];
  1009.     }
  1010.  
  1011.     // }}}
  1012.  
  1013.     /**
  1014.      * @param array information on a role as parsed from its xml file
  1015.      * @return true|PEAR_Error
  1016.      * @access private
  1017.      */
  1018.     function _addConfigVars($vars)
  1019.     {
  1020.         if (count($vars) > 3) {
  1021.             return $this->raiseError('Roles can only define 3 new config variables or less');
  1022.         }
  1023.         foreach ($vars as $name => $var) {
  1024.             if (!is_array($var)) {
  1025.                 return $this->raiseError('Configuration information must be an array');
  1026.             }
  1027.             if (!isset($var['type'])) {
  1028.                 return $this->raiseError('Configuration information must contain a type');
  1029.             } else {
  1030.                 if (!in_array($var['type'],
  1031.                       array('string', 'mask', 'password', 'directory', 'file', 'set'))) {
  1032.                     return $this->raiseError(
  1033.                         'Configuration type must be one of directory, file, string, ' .
  1034.                         'mask, set, or password');
  1035.                 }
  1036.             }
  1037.             if (!isset($var['default'])) {
  1038.                 return $this->raiseError(
  1039.                     'Configuration information must contain a default value ("default" index)');
  1040.             } else {
  1041.                 if (is_array($var['default'])) {
  1042.                     $real_default = '';
  1043.                     foreach ($var['default'] as $config_var => $val) {
  1044.                         if (strpos($config_var, 'text') === 0) {
  1045.                             $real_default .= $val;
  1046.                         } elseif (strpos($config_var, 'constant') === 0) {
  1047.                             if (defined($val)) {
  1048.                                 $real_default .= constant($val);
  1049.                             } else {
  1050.                                 return $this->raiseError(
  1051.                                     'Unknown constant "' . $val . '" requested in ' .
  1052.                                     'default value for configuration variable "' .
  1053.                                     $name . '"');
  1054.                             }
  1055.                         } elseif (isset($this->configuration_info[$config_var])) {
  1056.                             $real_default .=
  1057.                                 $this->configuration_info[$config_var]['default'];
  1058.                         } else {
  1059.                             return $this->raiseError(
  1060.                                 'Unknown request for "' . $config_var . '" value in ' .
  1061.                                 'default value for configuration variable "' .
  1062.                                 $name . '"');
  1063.                         }
  1064.                     }
  1065.                     $var['default'] = $real_default;
  1066.                 }
  1067.                 if ($var['type'] == 'integer') {
  1068.                     $var['default'] = (integer) $var['default'];
  1069.                 }
  1070.             }
  1071.             if (!isset($var['doc'])) {
  1072.                 return $this->raiseError(
  1073.                     'Configuration information must contain a summary ("doc" index)');
  1074.             }
  1075.             if (!isset($var['prompt'])) {
  1076.                 return $this->raiseError(
  1077.                     'Configuration information must contain a simple prompt ("prompt" index)');
  1078.             }
  1079.             if (!isset($var['group'])) {
  1080.                 return $this->raiseError(
  1081.                     'Configuration information must contain a simple group ("group" index)');
  1082.             }
  1083.             if (isset($this->configuration_info[$name])) {
  1084.                 return $this->raiseError('Configuration variable "' . $name .
  1085.                     '" already exists');
  1086.             }
  1087.             $this->configuration_info[$name] = $var;
  1088.         }
  1089.         return true;
  1090.     }
  1091.  
  1092.     // {{{ _encodeOutput(&data)
  1093.  
  1094.     /**
  1095.      * Encodes/scrambles configuration data before writing to files.
  1096.      * Currently, 'password' values will be base64-encoded as to avoid
  1097.      * that people spot cleartext passwords by accident.
  1098.      *
  1099.      * @param array (reference) array to encode values in
  1100.      *
  1101.      * @return bool TRUE on success
  1102.      *
  1103.      * @access private
  1104.      */
  1105.     function _encodeOutput(&$data)
  1106.     {
  1107.         foreach ($data as $key => $value) {
  1108.             if ($key == '__channels') {
  1109.                 foreach ($data['__channels'] as $channel => $blah) {
  1110.                     $this->_encodeOutput($data['__channels'][$channel]);
  1111.                 }
  1112.             }
  1113.             if (!isset($this->configuration_info[$key])) {
  1114.                 continue;
  1115.             }
  1116.             $type = $this->configuration_info[$key]['type'];
  1117.             switch ($type) {
  1118.                 // we base64-encode passwords so they are at least
  1119.                 // not shown in plain by accident
  1120.                 case 'password': {
  1121.                     $data[$key] = base64_encode($data[$key]);
  1122.                     break;
  1123.                 }
  1124.                 case 'mask': {
  1125.                     $data[$key] = octdec($data[$key]);
  1126.                     break;
  1127.                 }
  1128.             }
  1129.         }
  1130.         return true;
  1131.     }
  1132.  
  1133.     // }}}
  1134.     // {{{ _decodeInput(&data)
  1135.  
  1136.     /**
  1137.      * Decodes/unscrambles configuration data after reading from files.
  1138.      *
  1139.      * @param array (reference) array to encode values in
  1140.      *
  1141.      * @return bool TRUE on success
  1142.      *
  1143.      * @access private
  1144.      *
  1145.      * @see PEAR_Config::_encodeOutput
  1146.      */
  1147.     function _decodeInput(&$data)
  1148.     {
  1149.         if (!is_array($data)) {
  1150.             return true;
  1151.         }
  1152.         foreach ($data as $key => $value) {
  1153.             if ($key == '__channels') {
  1154.                 foreach ($data['__channels'] as $channel => $blah) {
  1155.                     $this->_decodeInput($data['__channels'][$channel]);
  1156.                 }
  1157.             }
  1158.             if (!isset($this->configuration_info[$key])) {
  1159.                 continue;
  1160.             }
  1161.             $type = $this->configuration_info[$key]['type'];
  1162.             switch ($type) {
  1163.                 case 'password': {
  1164.                     $data[$key] = base64_decode($data[$key]);
  1165.                     break;
  1166.                 }
  1167.                 case 'mask': {
  1168.                     $data[$key] = decoct($data[$key]);
  1169.                     break;
  1170.                 }
  1171.             }
  1172.         }
  1173.         return true;
  1174.     }
  1175.  
  1176.     // }}}
  1177.     // {{{ getDefaultChannel([layer])
  1178.     /**
  1179.      * Retrieve the default channel.
  1180.      *
  1181.      * On startup, channels are not initialized, so if the default channel is not
  1182.      * pear.php.net, then initialize the config.
  1183.      * @param string registry layer
  1184.      * @return string|false
  1185.      */
  1186.     function getDefaultChannel($layer = null)
  1187.     {
  1188.         $ret = false;
  1189.         if ($layer === null) {
  1190.             foreach ($this->layers as $layer) {
  1191.                 if (isset($this->configuration[$layer]['default_channel'])) {
  1192.                     $ret = $this->configuration[$layer]['default_channel'];
  1193.                     break;
  1194.                 }
  1195.             }
  1196.         } elseif (isset($this->configuration[$layer]['default_channel'])) {
  1197.             $ret = $this->configuration[$layer]['default_channel'];
  1198.         }
  1199.         if ($ret == 'pear.php.net' && defined('PEAR_RUNTYPE') && PEAR_RUNTYPE == 'pecl') {
  1200.             $ret = 'pecl.php.net';
  1201.         }
  1202.         if ($ret) {
  1203.             if ($ret != 'pear.php.net') {
  1204.                 $this->_lazyChannelSetup();
  1205.             }
  1206.             return $ret;
  1207.         }
  1208.         return PEAR_CONFIG_DEFAULT_CHANNEL;
  1209.     }
  1210.  
  1211.     // {{{ get(key, [layer])
  1212.     /**
  1213.      * Returns a configuration value, prioritizing layers as per the
  1214.      * layers property.
  1215.      *
  1216.      * @param string config key
  1217.      *
  1218.      * @return mixed the config value, or NULL if not found
  1219.      *
  1220.      * @access public
  1221.      */
  1222.     function get($key, $layer = null, $channel = false)
  1223.     {
  1224.         if (!isset($this->configuration_info[$key])) {
  1225.             return null;
  1226.         }
  1227.         if ($key == '__channels') {
  1228.             return null;
  1229.         }
  1230.         if ($key == 'default_channel') {
  1231.             return $this->getDefaultChannel($layer);
  1232.         }
  1233.         if (!$channel) {
  1234.             $channel = $this->getDefaultChannel();
  1235.         } elseif ($channel != 'pear.php.net') {
  1236.             $this->_lazyChannelSetup();
  1237.         }
  1238.         $channel = strtolower($channel);
  1239.         
  1240.         $test = (in_array($key, $this->_channelConfigInfo)) ?
  1241.             $this->_getChannelValue($key, $layer, $channel) :
  1242.             null;
  1243.         if ($test !== null) {
  1244.             if ($this->_installRoot) {
  1245.                 if (in_array($this->getGroup($key),
  1246.                       array('File Locations', 'File Locations (Advanced)')) &&
  1247.                       $this->getType($key) == 'directory') {
  1248.                     return $this->_prependPath($test, $this->_installRoot);
  1249.                 }
  1250.             }
  1251.             return $test;
  1252.         }
  1253.         if ($layer === null) {
  1254.             foreach ($this->layers as $layer) {
  1255.                 if (isset($this->configuration[$layer][$key])) {
  1256.                     $test = $this->configuration[$layer][$key];
  1257.                     if ($this->_installRoot) {
  1258.                         if (in_array($this->getGroup($key),
  1259.                               array('File Locations', 'File Locations (Advanced)')) &&
  1260.                               $this->getType($key) == 'directory') {
  1261.                             return $this->_prependPath($test, $this->_installRoot);
  1262.                         }
  1263.                     }
  1264.                     if ($key == 'preferred_mirror') {
  1265.                         $reg = &$this->getRegistry();
  1266.                         if (is_object($reg)) {
  1267.                             $chan = &$reg->getChannel($channel);
  1268.                             if (!$chan->getMirror($test) && $chan->getName() != $test) {
  1269.                                 return $channel; // mirror does not exist
  1270.                             }
  1271.                         }
  1272.                     }
  1273.                     return $test;
  1274.                 }
  1275.             }
  1276.         } elseif (isset($this->configuration[$layer][$key])) {
  1277.             $test = $this->configuration[$layer][$key];
  1278.             if ($this->_installRoot) {
  1279.                 if (in_array($this->getGroup($key),
  1280.                       array('File Locations', 'File Locations (Advanced)')) &&
  1281.                       $this->getType($key) == 'directory') {
  1282.                     return $this->_prependPath($test, $this->_installRoot);
  1283.                 }
  1284.             }
  1285.             if ($key == 'preferred_mirror') {
  1286.                 $reg = &$this->getRegistry();
  1287.                 if (is_object($reg)) {
  1288.                     $chan = &$reg->getChannel($channel);
  1289.                     if (!$chan->getMirror($test) && $chan->getName() != $test) {
  1290.                         return $channel; // mirror does not exist
  1291.                     }
  1292.                 }
  1293.             }
  1294.             return $test;
  1295.         }
  1296.         return null;
  1297.     }
  1298.  
  1299.     // }}}
  1300.     // {{{ _getChannelValue(key, value, [layer])
  1301.     /**
  1302.      * Returns a channel-specific configuration value, prioritizing layers as per the
  1303.      * layers property.
  1304.      *
  1305.      * @param string config key
  1306.      *
  1307.      * @return mixed the config value, or NULL if not found
  1308.      *
  1309.      * @access private
  1310.      */
  1311.     function _getChannelValue($key, $layer, $channel)
  1312.     {
  1313.         if ($key == '__channels' || $channel == 'pear.php.net') {
  1314.             return null;
  1315.         }
  1316.         $ret = null;
  1317.         if ($layer === null) {
  1318.             foreach ($this->layers as $ilayer) {
  1319.                 if (isset($this->configuration[$ilayer]['__channels'][$channel][$key])) {
  1320.                     $ret = $this->configuration[$ilayer]['__channels'][$channel][$key];
  1321.                     break;
  1322.                 }
  1323.             }
  1324.         } elseif (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
  1325.             $ret = $this->configuration[$layer]['__channels'][$channel][$key];
  1326.         }
  1327.         if ($key == 'preferred_mirror') {
  1328.             if ($ret !== null) {
  1329.                 $reg = &$this->getRegistry($layer);
  1330.                 if (is_object($reg)) {
  1331.                     $chan = &$reg->getChannel($channel);
  1332.                     if (!$chan->getMirror($ret) && $chan->getName() != $ret) {
  1333.                         return $channel; // mirror does not exist
  1334.                     }
  1335.                 }
  1336.                 return $ret;
  1337.             }
  1338.             if ($channel == $this->getDefaultChannel($layer)) {
  1339.                 return $channel; // we must use the channel name as the preferred mirror
  1340.                                  // if the user has not chosen an alternate
  1341.             } else {
  1342.                 return $this->getDefaultChannel($layer);
  1343.             }
  1344.         }
  1345.         return $ret;
  1346.     }
  1347.  
  1348.  
  1349.     // }}}
  1350.     // {{{ set(key, value, [layer])
  1351.  
  1352.     /**
  1353.      * Set a config value in a specific layer (defaults to 'user').
  1354.      * Enforces the types defined in the configuration_info array.  An
  1355.      * integer config variable will be cast to int, and a set config
  1356.      * variable will be validated against its legal values.
  1357.      *
  1358.      * @param string config key
  1359.      * @param string config value
  1360.      * @param string (optional) config layer
  1361.      * @param string channel to set this value for, or null for global value
  1362.      * @return bool TRUE on success, FALSE on failure
  1363.      */
  1364.     function set($key, $value, $layer = 'user', $channel = false)
  1365.     {
  1366.         if ($key == '__channels') {
  1367.             return false;
  1368.         }
  1369.         if (!isset($this->configuration[$layer])) {
  1370.             return false;
  1371.         }
  1372.         if ($key == 'default_channel') {
  1373.             // can only set this value globally
  1374.             $channel = 'pear.php.net';
  1375.             if ($value != 'pear.php.net') {
  1376.                 $this->_lazyChannelSetup($layer);
  1377.             }
  1378.         }
  1379.         if ($key == 'preferred_mirror') {
  1380.             if ($channel == '__uri') {
  1381.                 return false; // can't set the __uri pseudo-channel's mirror
  1382.             }
  1383.             $reg = &$this->getRegistry($layer);
  1384.             if (is_object($reg)) {
  1385.                 $chan = &$reg->getChannel($channel ? $channel : 'pear.php.net');
  1386.                 if (!$chan->getMirror($value) && $chan->getName() != $value) {
  1387.                     return false; // mirror does not exist
  1388.                 }
  1389.             }
  1390.         }
  1391.         if (empty($this->configuration_info[$key])) {
  1392.             return false;
  1393.         }
  1394.         extract($this->configuration_info[$key]);
  1395.         switch ($type) {
  1396.             case 'integer':
  1397.                 $value = (int)$value;
  1398.                 break;
  1399.             case 'set': {
  1400.                 // If a valid_set is specified, require the value to
  1401.                 // be in the set.  If there is no valid_set, accept
  1402.                 // any value.
  1403.                 if ($valid_set) {
  1404.                     reset($valid_set);
  1405.                     if ((key($valid_set) === 0 && !in_array($value, $valid_set)) ||
  1406.                         (key($valid_set) !== 0 && empty($valid_set[$value])))
  1407.                     {
  1408.                         return false;
  1409.                     }
  1410.                 }
  1411.                 break;
  1412.             }
  1413.         }
  1414.         if (!$channel) {
  1415.             $channel = $this->get('default_channel', null, 'pear.php.net');
  1416.         }
  1417.         if (!in_array($channel, $this->_channels)) {
  1418.             $this->_lazyChannelSetup($layer);
  1419.             $reg = &$this->getRegistry($layer);
  1420.             if ($reg) {
  1421.                 $channel = $reg->channelName($channel);
  1422.             }
  1423.             if (!in_array($channel, $this->_channels)) {
  1424.                 return false;
  1425.             }
  1426.         }
  1427.         if ($channel != 'pear.php.net') {
  1428.             if (in_array($key, $this->_channelConfigInfo)) {
  1429.                 $this->configuration[$layer]['__channels'][$channel][$key] = $value;
  1430.                 return true;
  1431.             } else {
  1432.                 return false;
  1433.             }
  1434.         } else {
  1435.             if ($key == 'default_channel') {
  1436.                 if (!isset($reg)) {
  1437.                     $reg = &$this->getRegistry($layer);
  1438.                     if (!$reg) {
  1439.                         $reg = &$this->getRegistry();
  1440.                     }
  1441.                 }
  1442.                 if ($reg) {
  1443.                     $value = $reg->channelName($value);
  1444.                 }
  1445.                 if (!$value) {
  1446.                     return false;
  1447.                 }
  1448.             }
  1449.         }
  1450.         $this->configuration[$layer][$key] = $value;
  1451.         if ($key == 'php_dir' && !$this->_noRegistry) {
  1452.             if (!isset($this->_registry[$layer]) ||
  1453.                   $value != $this->_registry[$layer]->install_dir) {
  1454.                 $this->_registry[$layer] = &new PEAR_Registry($value);
  1455.                 $this->_regInitialized[$layer] = false;
  1456.                 $this->_registry[$layer]->setConfig($this);
  1457.             }
  1458.         }
  1459.         return true;
  1460.     }
  1461.  
  1462.     // }}}
  1463.     function _lazyChannelSetup($uselayer = false)
  1464.     {
  1465.         if ($this->_noRegistry) {
  1466.             return;
  1467.         }
  1468.         $merge = false;
  1469.         foreach ($this->_registry as $layer => $p) {
  1470.             if ($uselayer && $uselayer != $layer) {
  1471.                 continue;
  1472.             }
  1473.             if (!$this->_regInitialized[$layer]) {
  1474.                 if ($layer == 'default' && isset($this->_registry['user']) ||
  1475.                       isset($this->_registry['system'])) {
  1476.                     // only use the default registry if there are no alternatives
  1477.                     continue;
  1478.                 }
  1479.                 if (!is_object($this->_registry[$layer])) {
  1480.                     if ($phpdir = $this->get('php_dir', $layer, 'pear.php.net')) {
  1481.                         $this->_registry[$layer] = &new PEAR_Registry($phpdir);
  1482.                         $this->_registry[$layer]->setConfig($this);
  1483.                         $this->_regInitialized[$layer] = false;
  1484.                     } else {
  1485.                         unset($this->_registry[$layer]);
  1486.                         return;
  1487.                     }
  1488.                 }
  1489.                 $this->setChannels($this->_registry[$layer]->listChannels(), $merge);
  1490.                 $this->_regInitialized[$layer] = true;
  1491.                 $merge = true;
  1492.             }
  1493.         }
  1494.     }
  1495.     // {{{ setChannels()
  1496.     
  1497.     /**
  1498.      * Set the list of channels.
  1499.      *
  1500.      * This should be set via a call to {@link PEAR_Registry::listChannels()}
  1501.      * @param array
  1502.      * @param bool
  1503.      * @return bool success of operation
  1504.      */
  1505.     function setChannels($channels, $merge = false)
  1506.     {
  1507.         if (!is_array($channels)) {
  1508.             return false;
  1509.         }
  1510.         if ($merge) {
  1511.             $this->_channels = array_merge($this->_channels, $channels);
  1512.         } else {
  1513.             $this->_channels = $channels;
  1514.         }
  1515.         foreach ($channels as $channel) {
  1516.             $channel = strtolower($channel);
  1517.             if ($channel == 'pear.php.net') {
  1518.                 continue;
  1519.             }
  1520.             foreach ($this->layers as $layer) {
  1521.                 if (!isset($this->configuration[$layer]['__channels'][$channel])
  1522.                       || !is_array($this->configuration[$layer]['__channels'][$channel])) {
  1523.                     $this->configuration[$layer]['__channels'][$channel] = array();
  1524.                 }
  1525.             }
  1526.         }
  1527.         return true;
  1528.     }
  1529.  
  1530.     // }}}
  1531.     // {{{ getType(key)
  1532.  
  1533.     /**
  1534.      * Get the type of a config value.
  1535.      *
  1536.      * @param string  config key
  1537.      *
  1538.      * @return string type, one of "string", "integer", "file",
  1539.      * "directory", "set" or "password".
  1540.      *
  1541.      * @access public
  1542.      *
  1543.      */
  1544.     function getType($key)
  1545.     {
  1546.         if (isset($this->configuration_info[$key])) {
  1547.             return $this->configuration_info[$key]['type'];
  1548.         }
  1549.         return false;
  1550.     }
  1551.  
  1552.     // }}}
  1553.     // {{{ getDocs(key)
  1554.  
  1555.     /**
  1556.      * Get the documentation for a config value.
  1557.      *
  1558.      * @param string  config key
  1559.      *
  1560.      * @return string documentation string
  1561.      *
  1562.      * @access public
  1563.      *
  1564.      */
  1565.     function getDocs($key)
  1566.     {
  1567.         if (isset($this->configuration_info[$key])) {
  1568.             return $this->configuration_info[$key]['doc'];
  1569.         }
  1570.         return false;
  1571.     }
  1572.        // }}}
  1573.     // {{{ getPrompt(key)
  1574.  
  1575.     /**
  1576.      * Get the short documentation for a config value.
  1577.      *
  1578.      * @param string  config key
  1579.      *
  1580.      * @return string short documentation string
  1581.      *
  1582.      * @access public
  1583.      *
  1584.      */
  1585.     function getPrompt($key)
  1586.     {
  1587.         if (isset($this->configuration_info[$key])) {
  1588.             return $this->configuration_info[$key]['prompt'];
  1589.         }
  1590.         return false;
  1591.     }
  1592.     // }}}
  1593.     // {{{ getGroup(key)
  1594.  
  1595.     /**
  1596.      * Get the parameter group for a config key.
  1597.      *
  1598.      * @param string  config key
  1599.      *
  1600.      * @return string parameter group
  1601.      *
  1602.      * @access public
  1603.      *
  1604.      */
  1605.     function getGroup($key)
  1606.     {
  1607.         if (isset($this->configuration_info[$key])) {
  1608.             return $this->configuration_info[$key]['group'];
  1609.         }
  1610.         return false;
  1611.     }
  1612.  
  1613.     // }}}
  1614.     // {{{ getGroups()
  1615.  
  1616.     /**
  1617.      * Get the list of parameter groups.
  1618.      *
  1619.      * @return array list of parameter groups
  1620.      *
  1621.      * @access public
  1622.      *
  1623.      */
  1624.     function getGroups()
  1625.     {
  1626.         $tmp = array();
  1627.         foreach ($this->configuration_info as $key => $info) {
  1628.             $tmp[$info['group']] = 1;
  1629.         }
  1630.         return array_keys($tmp);
  1631.     }
  1632.  
  1633.     // }}}
  1634.     // {{{ getGroupKeys()
  1635.  
  1636.     /**
  1637.      * Get the list of the parameters in a group.
  1638.      *
  1639.      * @param string $group parameter group
  1640.      *
  1641.      * @return array list of parameters in $group
  1642.      *
  1643.      * @access public
  1644.      *
  1645.      */
  1646.     function getGroupKeys($group)
  1647.     {
  1648.         $keys = array();
  1649.         foreach ($this->configuration_info as $key => $info) {
  1650.             if ($info['group'] == $group) {
  1651.                 $keys[] = $key;
  1652.             }
  1653.         }
  1654.         return $keys;
  1655.     }
  1656.  
  1657.     // }}}
  1658.     // {{{ getSetValues(key)
  1659.  
  1660.     /**
  1661.      * Get the list of allowed set values for a config value.  Returns
  1662.      * NULL for config values that are not sets.
  1663.      *
  1664.      * @param string  config key
  1665.      *
  1666.      * @return array enumerated array of set values, or NULL if the
  1667.      *               config key is unknown or not a set
  1668.      *
  1669.      * @access public
  1670.      *
  1671.      */
  1672.     function getSetValues($key)
  1673.     {
  1674.         if (isset($this->configuration_info[$key]) &&
  1675.             isset($this->configuration_info[$key]['type']) &&
  1676.             $this->configuration_info[$key]['type'] == 'set')
  1677.         {
  1678.             $valid_set = $this->configuration_info[$key]['valid_set'];
  1679.             reset($valid_set);
  1680.             if (key($valid_set) === 0) {
  1681.                 return $valid_set;
  1682.             }
  1683.             return array_keys($valid_set);
  1684.         }
  1685.         return null;
  1686.     }
  1687.  
  1688.     // }}}
  1689.     // {{{ getKeys()
  1690.  
  1691.     /**
  1692.      * Get all the current config keys.
  1693.      *
  1694.      * @return array simple array of config keys
  1695.      *
  1696.      * @access public
  1697.      */
  1698.     function getKeys()
  1699.     {
  1700.         $keys = array();
  1701.         foreach ($this->layers as $layer) {
  1702.             $test = $this->configuration[$layer];
  1703.             if (isset($test['__channels'])) {
  1704.                 foreach ($test['__channels'] as $channel => $configs) {
  1705.                     $keys = array_merge($keys, $configs);
  1706.                 }
  1707.             }
  1708.             unset($test['__channels']);
  1709.             $keys = array_merge($keys, $test);
  1710.         }
  1711.         return array_keys($keys);
  1712.     }
  1713.  
  1714.     // }}}
  1715.     // {{{ remove(key, [layer])
  1716.  
  1717.     /**
  1718.      * Remove the a config key from a specific config layer.
  1719.      *
  1720.      * @param string config key
  1721.      *
  1722.      * @param string (optional) config layer
  1723.      *
  1724.      * @return bool TRUE on success, FALSE on failure
  1725.      *
  1726.      * @access public
  1727.      */
  1728.     function remove($key, $layer = 'user')
  1729.     {
  1730.         $channel = $this->getDefaultChannel();
  1731.         if ($channel !== 'pear.php.net') {
  1732.             if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
  1733.                 unset($this->configuration[$layer]['__channels'][$channel][$key]);
  1734.                 return true;
  1735.             }
  1736.         }
  1737.         if (isset($this->configuration[$layer][$key])) {
  1738.             unset($this->configuration[$layer][$key]);
  1739.             return true;
  1740.         }
  1741.         return false;
  1742.     }
  1743.  
  1744.     // }}}
  1745.     // {{{ removeLayer(layer)
  1746.  
  1747.     /**
  1748.      * Temporarily remove an entire config layer.  USE WITH CARE!
  1749.      *
  1750.      * @param string config key
  1751.      *
  1752.      * @param string (optional) config layer
  1753.      *
  1754.      * @return bool TRUE on success, FALSE on failure
  1755.      *
  1756.      * @access public
  1757.      */
  1758.     function removeLayer($layer)
  1759.     {
  1760.         if (isset($this->configuration[$layer])) {
  1761.             $this->configuration[$layer] = array();
  1762.             return true;
  1763.         }
  1764.         return false;
  1765.     }
  1766.  
  1767.     // }}}
  1768.     // {{{ store([layer])
  1769.  
  1770.     /**
  1771.      * Stores configuration data in a layer.
  1772.      *
  1773.      * @param string config layer to store
  1774.      *
  1775.      * @return bool TRUE on success, or PEAR error on failure
  1776.      *
  1777.      * @access public
  1778.      */
  1779.     function store($layer = 'user', $data = null)
  1780.     {
  1781.         return $this->writeConfigFile(null, $layer, $data);
  1782.     }
  1783.  
  1784.     // }}}
  1785.     // {{{ toDefault(key)
  1786.  
  1787.     /**
  1788.      * Unset the user-defined value of a config key, reverting the
  1789.      * value to the system-defined one.
  1790.      *
  1791.      * @param string config key
  1792.      *
  1793.      * @return bool TRUE on success, FALSE on failure
  1794.      *
  1795.      * @access public
  1796.      */
  1797.     function toDefault($key)
  1798.     {
  1799.         trigger_error("PEAR_Config::toDefault() deprecated, use PEAR_Config::remove() instead", E_USER_NOTICE);
  1800.         return $this->remove($key, 'user');
  1801.     }
  1802.  
  1803.     // }}}
  1804.     // {{{ definedBy(key)
  1805.  
  1806.     /**
  1807.      * Tells what config layer that gets to define a key.
  1808.      *
  1809.      * @param string config key
  1810.      * @param boolean return the defining channel
  1811.      *
  1812.      * @return string|array the config layer, or an empty string if not found.
  1813.      *
  1814.      *         if $returnchannel, the return is an array array('layer' => layername,
  1815.      *         'channel' => channelname), or an empty string if not found
  1816.      *
  1817.      * @access public
  1818.      */
  1819.     function definedBy($key, $returnchannel = false)
  1820.     {
  1821.         foreach ($this->layers as $layer) {
  1822.             $channel = $this->getDefaultChannel();
  1823.             if ($channel !== 'pear.php.net') {
  1824.                 if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
  1825.                     if ($returnchannel) {
  1826.                         return array('layer' => $layer, 'channel' => $channel);
  1827.                     }
  1828.                     return $layer;
  1829.                 }
  1830.             }
  1831.             if (isset($this->configuration[$layer][$key])) {
  1832.                 if ($returnchannel) {
  1833.                     return array('layer' => $layer, 'channel' => 'pear.php.net');
  1834.                 }
  1835.                 return $layer;
  1836.             }
  1837.         }
  1838.         return '';
  1839.     }
  1840.  
  1841.     // }}}
  1842.     // {{{ isDefaulted(key)
  1843.  
  1844.     /**
  1845.      * Tells whether a config value has a system-defined value.
  1846.      *
  1847.      * @param string   config key
  1848.      *
  1849.      * @return bool
  1850.      *
  1851.      * @access public
  1852.      *
  1853.      * @deprecated
  1854.      */
  1855.     function isDefaulted($key)
  1856.     {
  1857.         trigger_error("PEAR_Config::isDefaulted() deprecated, use PEAR_Config::definedBy() instead", E_USER_NOTICE);
  1858.         return $this->definedBy($key) == 'system';
  1859.     }
  1860.  
  1861.     // }}}
  1862.     // {{{ isDefined(key)
  1863.  
  1864.     /**
  1865.      * Tells whether a given key exists as a config value.
  1866.      *
  1867.      * @param string config key
  1868.      *
  1869.      * @return bool whether <config key> exists in this object
  1870.      *
  1871.      * @access public
  1872.      */
  1873.     function isDefined($key)
  1874.     {
  1875.         foreach ($this->layers as $layer) {
  1876.             if (isset($this->configuration[$layer][$key])) {
  1877.                 return true;
  1878.             }
  1879.         }
  1880.         return false;
  1881.     }
  1882.  
  1883.     // }}}
  1884.     // {{{ isDefinedLayer(key)
  1885.  
  1886.     /**
  1887.      * Tells whether a given config layer exists.
  1888.      *
  1889.      * @param string config layer
  1890.      *
  1891.      * @return bool whether <config layer> exists in this object
  1892.      *
  1893.      * @access public
  1894.      */
  1895.     function isDefinedLayer($layer)
  1896.     {
  1897.         return isset($this->configuration[$layer]);
  1898.     }
  1899.  
  1900.     // }}}
  1901.     // {{{ getLayers()
  1902.  
  1903.     /**
  1904.      * Returns the layers defined (except the 'default' one)
  1905.      *
  1906.      * @return array of the defined layers
  1907.      */
  1908.     function getLayers()
  1909.     {
  1910.         $cf = $this->configuration;
  1911.         unset($cf['default']);
  1912.         return array_keys($cf);
  1913.     }
  1914.  
  1915.     // }}}
  1916.     // {{{ apiVersion()
  1917.     function apiVersion()
  1918.     {
  1919.         return '1.1';
  1920.     }
  1921.     // }}}
  1922.  
  1923.     /**
  1924.      * @return PEAR_Registry
  1925.      */
  1926.     function &getRegistry($use = null)
  1927.     {
  1928.         if ($use === null) {
  1929.             $layer = 'user';
  1930.         } else {
  1931.             $layer = $use;
  1932.         }
  1933.         if (isset($this->_registry[$layer])) {
  1934.             return $this->_registry[$layer];
  1935.         } elseif ($use === null && isset($this->_registry['system'])) {
  1936.             return $this->_registry['system'];
  1937.         } elseif ($use === null && isset($this->_registry['default'])) {
  1938.             return $this->_registry['default'];
  1939.         } elseif ($use) {
  1940.             $a = false;
  1941.             return $a;
  1942.         } else {
  1943.             // only go here if null was passed in
  1944.             die("CRITICAL ERROR: Registry could not be initialized from any value");
  1945.         }
  1946.     }
  1947.     /**
  1948.      * This is to allow customization like the use of installroot
  1949.      * @param PEAR_Registry
  1950.      * @return bool
  1951.      */
  1952.     function setRegistry(&$reg, $layer = 'user')
  1953.     {
  1954.         if ($this->_noRegistry) {
  1955.             return false;
  1956.         }
  1957.         if (!in_array($layer, array('user', 'system'))) {
  1958.             return false;
  1959.         }
  1960.         $this->_registry[$layer] = &$reg;
  1961.         if (is_object($reg)) {
  1962.             $this->_registry[$layer]->setConfig($this);
  1963.         }
  1964.         return true;
  1965.     }
  1966.  
  1967.     function noRegistry()
  1968.     {
  1969.         $this->_noRegistry = true;
  1970.     }
  1971.  
  1972.     /**
  1973.      * @return PEAR_Remote
  1974.      */
  1975.     function &getRemote()
  1976.     {
  1977.         $remote = &new PEAR_Remote($this);
  1978.         return $remote;
  1979.     }
  1980.  
  1981.     /**
  1982.      * @return PEAR_REST
  1983.      */
  1984.     function &getREST($version, $options = array())
  1985.     {
  1986.         $version = str_replace('.', '', $version);
  1987.         if (!class_exists($class = 'PEAR_REST_' . $version)) {
  1988.             require_once 'PEAR/REST/' . $version . '.php';
  1989.         }
  1990.         $remote = &new $class($this, $options);
  1991.         return $remote;
  1992.     }
  1993.  
  1994.     /**
  1995.      * The ftp server is set in {@link readFTPConfigFile()}.  It exists only if a
  1996.      * remote configuration file has been specified
  1997.      * @return PEAR_FTP|false
  1998.      */
  1999.     function &getFTP()
  2000.     {
  2001.         if (isset($this->_ftp)) {
  2002.             return $this->_ftp;
  2003.         } else {
  2004.             $a = false;
  2005.             return $a;
  2006.         }
  2007.     }
  2008.  
  2009.     // {{{ _prependPath($path, $prepend)
  2010.  
  2011.     function _prependPath($path, $prepend)
  2012.     {
  2013.         if (strlen($prepend) > 0) {
  2014.             if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {
  2015.                 if (preg_match('/^[a-z]:/i', $prepend)) {
  2016.                     $prepend = substr($prepend, 2);
  2017.                 } elseif ($prepend{0} != '\\') {
  2018.                     $prepend = "\\$prepend";
  2019.                 }
  2020.                 $path = substr($path, 0, 2) . $prepend . substr($path, 2);
  2021.             } else {
  2022.                 $path = $prepend . $path;
  2023.             }
  2024.         }
  2025.         return $path;
  2026.     }
  2027.     // }}}
  2028.  
  2029.     /**
  2030.      * @param string|false installation directory to prepend to all _dir variables, or false to
  2031.      *                     disable
  2032.      */
  2033.     function setInstallRoot($root)
  2034.     {
  2035.         if (substr($root, -1) == DIRECTORY_SEPARATOR) {
  2036.             $root = substr($root, 0, -1);
  2037.         }
  2038.         $old = $this->_installRoot;
  2039.         $this->_installRoot = $root;
  2040.         if (($old != $root) && !$this->_noRegistry) {
  2041.             foreach (array_keys($this->_registry) as $layer) {
  2042.                 if ($layer == 'ftp' || !isset($this->_registry[$layer])) {
  2043.                     continue;
  2044.                 }
  2045.                 $this->_registry[$layer] =
  2046.                     &new PEAR_Registry($this->get('php_dir', $layer, 'pear.php.net'));
  2047.                 $this->_registry[$layer]->setConfig($this);
  2048.                 $this->_regInitialized[$layer] = false;
  2049.             }
  2050.         }
  2051.     }
  2052. }
  2053.  
  2054. ?>
  2055.